package name.huliqing.qfaces.temp;
//package name.huliqing.qfaces.component;
//
//import java.io.IOException;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.logging.Logger;
//import javax.el.MethodExpression;
//import javax.faces.component.UIColumn;
//import javax.faces.component.UIComponent;
//import javax.faces.component.UIComponentBase;
//import javax.faces.component.UIData;
//import javax.faces.component.UIForm;
//import javax.faces.component.html.HtmlOutputLink;
//import javax.faces.component.html.HtmlGraphicImage;
//import javax.faces.component.html.HtmlOutputText;
//import javax.faces.component.html.HtmlPanelGroup;
//import javax.faces.context.FacesContext;
//import javax.faces.context.ResponseWriter;
//import javax.servlet.http.HttpServletRequest;
//import name.huliqing.qfaces.QFaces;
//import name.huliqing.qfaces.model.PageModel;
//import name.huliqing.qfaces.model.PageParam;
// 
///**
// * 
// * @author huliqing
// *
// */
//public class ____20100629_Scroller extends UIComponentBase {
//	private final static Logger logger = Logger.getLogger(____20100629_Scroller.class.getName());
//	
//	// ---- 主要的控件参数:
//	
//	// 组件绑定的dataTable的id
//	private String  _for;
//	
//	// 方法绑定，用于从Bean中获取data
//	private MethodExpression bind;
//	
//	// 请参考UIData的var属性
//	private String var;
//	
//	// [top,bottom,both] 将scroller显示在上部还是下部,默认下部
//	private String  _display;
//	
//	// [Number]显示的页面数,数字类型
//	private Long    _displayPage;
//	
//	// [true,false]是否显示总记录数,默认true
//	private Boolean _displayCount;
//	
//	// [true,false]是否通过input进行跳转,默认true,通过在input中输入页面跳转
//	private Boolean _displayJump;
//	
//	// [true,false]是否通过select框进行跳转,默认false
//	private Boolean _displayJumpBySelect;
//	
//	// 每页显示数量
//	private Integer _pageSize;
//	
//	// "总记录数"的文字描述
//	private String _strRecordTotal;
//	
//	// "总页数"的文字描述
//	private String _strPageTotal;
//	
//	// "跳转"按钮的文字描述
//	private String _strJump;
//	
//	// 是否渲染组件,如果false,则不渲染翻页导航条，看起来没有一点作用。
//	// 实际上这可以与t:dataTable（MyFaces)配合使用，组件为t:dataTable提供分页数据，
//	// 页t:scroller渲染分页导航,因为q:scroller渲染的分页条是固定位置的，可能存在不够自由的地方
//	private Boolean _visible;
//	
//	// 用于排序的字段，格式像这样： “field1,field2,field3”,即通过“，”号分隔
//	private String _sortFields;
//	
//	// Scroller 的CSS样式
//	private String _style;
//	
//	// New “上一页”的图片路径
//	private String _srcPagePrevious;
//	private String _srcPageNext;
//	private String _srcPageFirst;
//	private String _srcPageLast;
//
//	// 翻页栏的样式
//	private String styleClassMouseOn;
//	private String styleClassMouseOut;
//	private String styleClassCurrent;
//	// 翻页图片的外div的样式,(鼠标响应时的样式)
//	private String styleClassImageMouseOn;
//	private String styleClassImageMouseOut;
//	
//	// 外观样式0,1...默认0
//	private int face;
//	
//	// ---- URL参数
//	
//	private String CONS_RECORD_START = "qRecordStart";
//	private String CONS_RECORD_SORT_BY = "qRecordSortBy";
//	private String CONS_RECORD_SORT_ASC = "qRecordSortAsc";
//	
//	// ---- 内部参数及方法绑定 
//	
//	// 用于存储起始记录,起始记录优先从parameter中的CONS_RECORD_START中获取,
//	// 如果parameter中没有CONS_RECORD_START,再从recordStart中恢复,如果仍然
//	// 没有,则设为0,这样可以方便用户通过URL直接进行传递，而不影响页数
//	private Long pRecordStart;
//	
//	// 总记录数
//	private Long pRecordTotal;
//	
//	// 总页数
//	private Long pPageTotal;
//	
//	// 显示在界面上用于翻页的最多页数
//	private Long pPageDisplay;
//	
//	// 当前页
//	private Long pPageCurrent;
//	
//	// 二维数组,pPages[n][2]用于显示的页数数组 <<- p1 p2 p3 ... ->>
//	private long[][] pPages;
//	
//	// 当前的排序字段
//	private String _sortField;
//	
//	// 是否是倒序的。
//	private Boolean _isAsc;
//	
//	
//	public void setBind(MethodExpression bind) {
//		this.bind = bind;
//	}
//
//	@Override
//    public void restoreState(FacesContext fc, Object state) {
//		Object[] obj = (Object[]) state;
//		super.restoreState(fc, obj[0]);
//		this.bind = (MethodExpression) obj[1];
//		this.pRecordStart = (Long) obj[2];
//		this._sortField = (String) obj[3];
//		this._isAsc = (Boolean) obj[4];
//		this.var = (String) obj[5];
//	}
//	
//	@Override
//    public Object saveState(FacesContext fc) {
//		// _sortField,_isAsc这个状态必须保存，因为用户可能使用actionListener或提交表单，
//		// 而使CONS_RECORD_START不存在, bind属性同样
//		Object[] obj = new Object[6];
//		obj[0] = super.saveState(fc);
//		obj[1] = this.bind;
//		obj[2] = this.pRecordStart;
//		obj[3] = this._sortField;
//		obj[4] = this._isAsc;
//		obj[5] = this.var;
//		return obj;
//	}
//	
//	@Override
//    public void encodeBegin(FacesContext fc) throws IOException {
//		// 组件绑定的JS资源
//		QFaces.getResLoader2().loadJavaScript(this, "Scroller.js");
//		
//		// 处理属性参数
//		this._for = (String) this.getAttributes().get("for");
//		this.var = (String) this.getAttributes().get("var");
//		this._display = (String) this.getAttributes().get("display");
//		this._displayPage = QFaces.convertToLong(QFaces.getAttribute(this, "displayPage", 10L));
//		this._displayCount = QFaces.convertToBoolean(QFaces.getAttribute(this, "displayCount", Boolean.TRUE));
//		this._displayJump = QFaces.convertToBoolean(QFaces.getAttribute(this, "displayJump", Boolean.TRUE));
//		this._displayJumpBySelect = QFaces.convertToBoolean(QFaces.getAttribute(this, "displayJumpBySelect", Boolean.FALSE));
//		this._sortFields = (String) this.getAttributes().get("sortFields");
//		this._pageSize = QFaces.convertToInteger(QFaces.getAttribute(this, "pageSize", 20));
//		this._visible = QFaces.convertToBoolean(QFaces.getAttribute(this, "visible", Boolean.TRUE));
//		this._style = (String) QFaces.getAttribute(this, "style", "");
//		this.styleClassMouseOn = (String) QFaces.getAttribute(this, "styleClassMouseOn", "_qf_01_mouseOn");
//		this.styleClassMouseOut = (String) QFaces.getAttribute(this, "styleClassMouseOut", "_qf_01_mouseOut");
//		this.styleClassCurrent = (String) QFaces.getAttribute(this, "styleClassCurrent", "_qf_01_current");
//		this.styleClassImageMouseOn = (String) QFaces.getAttribute(this, "styleClassImageMouseOn", "_qf_01_imageMouseOn");
//		this.styleClassImageMouseOut = (String) QFaces.getAttribute(this, "styleClassImageMouseOut", "_qf_01_imageMouseOut");
//		this.face = QFaces.convertToInteger(QFaces.getAttribute(this, "face", 0));
//		
//		if (this._for == null) 
//			throw new NullPointerException("Target not found(attribute 'for')");
//		if (this._display == null || (!_display.equalsIgnoreCase("top") && !_display.equalsIgnoreCase("bottom") && !_display.equalsIgnoreCase("both")))
//			this._display = "bottom";
//		// 目前face只支持0,1
//		if (this.face > 1 || this.face < 0)
//			this.face = 0;
//
//		// 处理字符串参数
//		this._strRecordTotal = (String) QFaces.getAttribute(this, "strRecordTotal", "总记录:");
//		this._strPageTotal = (String) QFaces.getAttribute(this, "strPageTotal", "页数:");
//		this._strJump = (String) QFaces.getAttribute(this, "strJump", "转到");
//		
//		// 处理翻页图片参数
//		this._srcPagePrevious = (String) QFaces.getAttribute(this, "srcPagePrevious", QFaces.getResLoader2().makeImageSrc("01-" + this.face + "-page-previous.gif"));
//		this._srcPageNext = (String) QFaces.getAttribute(this, "srcPageNext", QFaces.getResLoader2().makeImageSrc("01-" + this.face + "-page-next.gif"));
//		this._srcPageFirst = (String) QFaces.getAttribute(this, "srcPageFirst", QFaces.getResLoader2().makeImageSrc("01-" + this.face + "-page-first.gif"));
//		this._srcPageLast = (String) QFaces.getAttribute(this, "srcPageLast", QFaces.getResLoader2().makeImageSrc("01-" + this.face + "-page-last.gif"));
//		
//		// ---- 以下非外部参数
//		
//		String scroller_asc = QFaces.getResLoader2().makeImageSrc("01-asc.png");
//		String scroller_desc = QFaces.getResLoader2().makeImageSrc("01-desc.png");
//		
//		// ---- 开始逻辑
//		
//		Object targetTemp = null;
//		UIData target = null;
//		MethodExpression _bind = null;
//		PageModel<Object> pageModel = null;
//		
//		targetTemp = this.findComponent(_for);
//		if (!(targetTemp instanceof javax.faces.component.UIData))
//			logger.severe("Target UIData not found!");
//		
//		target = (UIData) targetTemp;
//		
//		// 计算起始记录,
//		calculateRecordStart(target);
//		
//		// 计算排序信息
//		calculateSortBy();
//		
//		PageParam pageParam = new PageParam(this.pRecordStart, this._pageSize, this._sortField, this._isAsc);
//		_bind = QFaces.createMethodExpression(this.bind.getExpressionString(), 
//				PageModel.class, new Class[]{PageParam.class});
//		if (_bind == null) 
//			logger.severe("\"bind\" method not found, " +
//					"check the attribute of \"bind\" and the binding method of your backing bean.");
//		pageModel = (PageModel<Object>) _bind.invoke(fc.getELContext(), new Object[]{pageParam});
//		
//		// 如果找不到数据则创建一个空的.
//		if (pageModel == null) {
//			pageModel = new PageModel<Object>();
//			logger.warning("...!!! NullPointerException:No data with the PageModel(" + this.getClass().getName() + ")");
//		}
//		
//		// 绑定数据
//		target.setValue(pageModel.getPageData());
//		
//		// 绑定引用var
//		if (this.var != null)
//			target.setVar(this.var);
//		
//		// 获取total数据
//		this.pRecordTotal = pageModel.getTotal();
//		
//		// 计算总页数
//		this.pPageTotal = calculatePageTotal(pageModel, this._pageSize);
//		
//		// 最多显示的页码
//		this.pPageDisplay = _displayPage;
//		
//		// 计算用于在页面显示的页码
//		this.pPages = calculatePages( this.pPageTotal, this.pPageDisplay, this.pRecordStart, this._pageSize );
//		
//		// 计算当前所在的页面
//		this.pPageCurrent = calculatePageCurrent(this.pRecordStart, this._pageSize);
//		
//		// ------------------------------------- 关于排序
//		
//		// Before Render children
//		// Pre encodeChildren: 创建表头,创建排序字段
//		if (this._sortFields != null) {
//			UIData uiData = (UIData) this.findComponent(this._for);
//			// 用于排序的各个字串
//			String[] sortFields = this._sortFields.split(",");
//			// 找出UIData 下的所有UIColumn
//			List<UIComponent> children = uiData.getChildren();
//			List<UIColumn> columns = new ArrayList<UIColumn>();
//			for (UIComponent child : children) {
//				if (child instanceof UIColumn) {
//					columns.add((UIColumn) child);
//				}
//			}
//			if (sortFields != null && sortFields.length > 0 && columns.size() > 0) {
//				for (int i = 0; i < sortFields.length; i++) {
//					if (i >= columns.size()) {
//						break;
//					}
//					String sortField = sortFields[i].trim();
//					// 用于排序的字段名，如果为null或空，则超过
//					if (sortField.equals("")) {
//						continue;
//					}
//					// UIData下的column下必须有name为header的facet才能添加排序
//					UIColumn column = columns.get(i);
//					UIComponent header = column.getFacet("header");
//					if (header == null) {
//						continue;
//					}
//					String title = (String) ((HtmlOutputText) header).getValue();
//					UIForm uiForm = this.getForm(this);
//					String formId = (uiForm != null ? uiForm.getClientId(fc) : "");
//
//					HtmlPanelGroup group = (HtmlPanelGroup) fc.getApplication().createComponent(HtmlPanelGroup.COMPONENT_TYPE);
//					HtmlOutputLink sortLink = (HtmlOutputLink) fc.getApplication().createComponent(HtmlOutputLink.COMPONENT_TYPE);
//					HtmlOutputText text = (HtmlOutputText) fc.getApplication().createComponent(HtmlOutputText.COMPONENT_TYPE);
//					HtmlGraphicImage image = null;
//					// 这可以保证组件不会进行状态保存，否则会引起ID重复的问题
//					group.setTransient(true);
//					
//					StringBuilder URLPrefix = new StringBuilder(this.getURL(fc));
//					URLPrefix.append("?").append(CONS_RECORD_SORT_BY).append("=").append(sortField);
//					URLPrefix.append("&").append(CONS_RECORD_START).append("=0");	// 排序时将起始行置为0;
//					URLPrefix.append("&").append(CONS_RECORD_SORT_ASC).append("=");
//					
//					if (sortField.equalsIgnoreCase(this._sortField)) {
//						image = (HtmlGraphicImage) fc.getApplication().createComponent(HtmlGraphicImage.COMPONENT_TYPE);
//						image.setStyle("vertical-align:middle;");
//						if (this._isAsc) {
//							URLPrefix.append("false");
//							image.setUrl(scroller_asc);
//						} else {
//							URLPrefix.append("true");
//							image.setUrl(scroller_desc);
//						}
//					} else {
//						URLPrefix.append("true");
//					}
//					text.setValue(title);
//					sortLink.setValue("#");
//					sortLink.getChildren().add(text);
//					sortLink.setOnclick("Q.F.UIScroller.sortLink('" + URLPrefix + "', '" + formId + "')");
//					group.getChildren().add(sortLink);
//					if (image != null) {
//						group.getChildren().add(image);
//					}
//					logger.fine("Before put new header......");
//					column.getFacets().clear();
//					column.getFacets().put("header", group);
//					logger.fine("After put new header......");
//				}
//			}
//		}
//		
//		// ---- 开始渲染Scroller组件
//		
//		ResponseWriter rw = fc.getResponseWriter();
//		rw.startElement("div", this);
//		rw.writeAttribute("style", "border:0;", null);
//		if (this._display.equalsIgnoreCase("top") 
//				|| this._display.equalsIgnoreCase("both")) {
//			if (this._visible) {
//				encodeScroller(fc, "top");				
//			}
//		}
//	}
//	
//	@Override
//	public void encodeChildren(FacesContext fc) throws IOException {
//		super.encodeChildren(fc);
//	}
//	
//	@Override
//	public void encodeEnd(FacesContext fc) throws IOException {
//		ResponseWriter rw = fc.getResponseWriter();
//		if (this._display.equalsIgnoreCase("bottom") 
//				|| this._display.equalsIgnoreCase("both")) {
//			if (this._visible) {
//				encodeScroller(fc, "bottom");
//			}
//		}
//		rw.endElement("div");
//	}
//	
//	// ---------- encode scroller
//	
//	// position参数只是为标识是top scroller还是bottom scroller,因为组件可以同时渲染在两个地方(top,bottom)
//	private void encodeScroller(FacesContext fc, String position) throws IOException {
//		// 如果存在排序信息，则需要添加排序参数到URL请求参数中
//		String URLPrefix = null;
//		if (this._sortField != null && !this._sortField.equals("")) {
//			URLPrefix = getURL(fc) + 
//			"?" + CONS_RECORD_SORT_BY + "=" + this._sortField + 
//			"&" + CONS_RECORD_SORT_ASC + "=" + this._isAsc + 
//			"&" + CONS_RECORD_START + "="; // URL前缀;
//		} else {
//			URLPrefix = getURL(fc) + 
//			"?" + CONS_RECORD_START + "="; // URL前缀
//		}
//		
//		// 加入form主要是为了让js能够提交该form.如果通过简单的OutputLink方式跳转页面，
//		// 则不够完美，会让页面中form里的其它field无法提交，这会让其它field所绑定的BackingBean
//		// 的数据重置，而不能恢复原来的值，这对页面查询（搜索）分页时保存搜索条件时非常有用
//		UIForm uiForm = getForm(this);
//		String formId = (uiForm != null ? uiForm.getClientId(fc) : "");
//		
//		// 开始渲染scroller
//		ResponseWriter rw = fc.getResponseWriter();
//		rw.startElement("table", this);
//		rw.writeAttribute("border", "0", null);
//		rw.writeAttribute("cellspacing", "0", null);
//		rw.writeAttribute("cellpadding", "1", null);
//		rw.writeAttribute("style", this._style, null);
//		rw.startElement("tr", this);
//		
//		// encode 箭头 <<
//		encodeArrowPrevious(fc, URLPrefix, formId);
//		
//		// encode 翻页
//		// page[0]为页码，page[1]为当前页的起始记录, url为跳转的目的地址（通过form的post方式跳转）
//		// currentPage 表示是否为当前页，在当前页下，渲染输出会不一样，以提醒用户当前所在的页码
//		rw.startElement("td", this);
//			rw.startElement("table", this);
//			rw.writeAttribute("border", "0", null);
//			rw.startElement("tr", this);
//			for (long[] page : this.pPages) {
//				String url = URLPrefix + page[1];
//				String label = String.valueOf(page[0] + 1);
//				Boolean currentPage = (this.pPageCurrent == page[0]);
//				encodeTD(rw, formId, label, url, currentPage);
//			}
//			rw.endElement("tr");
//			rw.endElement("table");
//		rw.endElement("td");
//		
//		// encode 箭头 >>
//		encodeArrowNext(fc, URLPrefix, formId);
//		
//		// encode 总记录
//		if (this._displayCount) 
//			encodeInfo(rw);
//		
//		// encode JUMP To
//		if (this._displayJump) 
//			encodeJump(fc, URLPrefix, formId, position);
//		
//		// End encode
//		rw.endElement("tr");
//		rw.endElement("table");
//	}
//	
//	
//	private void encodeTD(ResponseWriter rw, String formId, String label, String url, boolean currentPage) throws IOException {
//		String jsEvent = "Q.F.UIScroller.pageLinkEvent(this, '" + url + "', '" + formId + "');";
//		rw.startElement("td", this);
//		rw.writeAttribute("style", "text-align:center;", null);
//		if (currentPage) { // 如果是当前页，则加粗
//			rw.writeAttribute("class", this.styleClassCurrent, null);
//			rw.writeText(label, null);
//		} else {
//			rw.writeAttribute("class", this.styleClassMouseOut, null);
//			rw.writeAttribute("onmouseover", "this.className='" + this.styleClassMouseOn + "'", null);
//			rw.writeAttribute("onmouseout", "this.className='" + this.styleClassMouseOut + "'", null);
//			rw.writeAttribute("onclick", jsEvent, null);
//			rw.writeText(label, null);
//		}
//		rw.endElement("td");
//	}
//	
//	
//	private String getURL(FacesContext fc) {
//		HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
//		String viewId = request.getServletPath();
//		String contextPath = fc.getExternalContext().getRequestContextPath();
//		return (contextPath + viewId);
//	}
//	
//	private void encodeJump(FacesContext fc, String URLPrefix, String formId, String position) throws IOException {
//		ResponseWriter rw = fc.getResponseWriter();
//
//		// 渲染select进行跳转，
//		if (this._displayJumpBySelect) {
//			StringBuilder js = new StringBuilder("Q.F.UIScroller.jumpTo(")
//			.append(" '" + URLPrefix + "'")
//			.append(",this.value")
//			.append(",'" + formId + "'")
//			.append(")");
//			
//			rw.startElement("td", this);
//			rw.startElement("select", this);
//			rw.writeAttribute("size", "1", null);
//			rw.writeAttribute("onchange", js, null);
//			for (int i = 0; i < this.pPageTotal; i++) {
//				rw.startElement("option", this);
//				rw.writeAttribute("value", i * this._pageSize, null);
//				if (i == this.pPageCurrent) {
//					rw.writeAttribute("selected", "true", null);
//				}
//				rw.writeText(i + 1, null);
//				rw.endElement("option");
//			}
//			rw.endElement("select");
//			rw.endElement("td");
//		}
//		
//		// ---- 渲染input框进行跳转
//		
//		if (this._displayJump) {
//			// 用于跳转的input field的ID, 必须加上position以区别,因为组件可能同时渲染在top和bottom
//			// 如果没有区别，则会渲染出两个相同ID的input field;
//			String idOfInputJump = this.getClientId(fc) + ":idOfInputJump:" + position;
//			
//			StringBuilder js_jumpByEnter = new StringBuilder("Q.F.UIScroller.jumpByEnter(")
//			.append(" '" + URLPrefix + "'")
//			.append(",'" + idOfInputJump + "'")
//			.append(",'" + formId + "'")
//			.append(",'" + this._pageSize + "'")
//			.append(",'" + this.pPageTotal + "'")
//			.append(",event")
//			.append(")");
//			
//			StringBuilder js_jumpByClick = new StringBuilder("Q.F.UIScroller.jumpByClick(")
//			.append(" '" + URLPrefix + "'")
//			.append(",'" + idOfInputJump + "'")	// idOfInputJump
//			.append(",'" + formId + "'")
//			.append(",'" + this._pageSize + "'")
//			.append(",'" + this.pPageTotal + "'")
//			.append(")");
//			
//			rw.startElement("td", this);
//			rw.startElement("input", this);
//			rw.writeAttribute("id", idOfInputJump, null);
//			rw.writeAttribute("name", idOfInputJump, null);
//			rw.writeAttribute("type", "text", null);
//			rw.writeAttribute("style", "width:40px;", null);
//			rw.writeAttribute("value", (this.pPageCurrent + 1), null);
//			rw.writeAttribute("onkeydown", js_jumpByEnter, null);
//			rw.endElement("input");
//			rw.startElement("input", this);
//			rw.writeAttribute("type", "button", null);
//			rw.writeAttribute("value", this._strJump, null);
//			rw.writeAttribute("onclick", js_jumpByClick, null);
//			rw.endElement("input");
//			rw.endElement("td");
//		}
//	}
//	
//	private void encodeInfo(ResponseWriter rw) throws IOException {
//		rw.startElement("td", this);
//		rw.writeText(this._strRecordTotal + this.pRecordTotal, null);
//		rw.endElement("td");
//		rw.startElement("td", this);
//		rw.writeText(this._strPageTotal + this.pPageTotal, null);
//		rw.endElement("td");
//	}
//
//	
//	private void encodeArrowPrevious(FacesContext fc, String URLPrefix, String formId) throws IOException {
//		// 是否需要渲染事件响应，因为达到第一页时，是不需要再响应“向前翻页”动作的
//		Boolean previousEvent = this.pPageCurrent > 0;
//		
//		// 计算首页及前一页起始记录
//		Long record_first = 0L;
//		Long record_previous = (this.pPageCurrent - 1) * this._pageSize;
//		
//		// 事件响应
//		StringBuilder jsEvent_first = new StringBuilder("Q.F.UIScroller.imageLink(")
//		.append(" \"" + URLPrefix + "\"")
//		.append(",\"" + record_first + "\"")
//		.append(",\"" + formId + "\"")
//		.append(")");
//		
//		StringBuilder jsEvent_previous = new StringBuilder("Q.F.UIScroller.imageLink(")
//		.append(" \"" + URLPrefix + "\"")
//		.append(",\"" + record_previous + "\"")
//		.append(",\"" + formId + "\"")
//		.append(")");
//		
//		// 翻到第一页
//		ResponseWriter rw = fc.getResponseWriter();
//		rw.startElement("td", this);
//		this.encodeImage(fc, this._srcPageFirst, (previousEvent ? jsEvent_first.toString() : null));
//		rw.endElement("td");
//		
//		// 翻到前一页
//		rw.startElement("td", this);
//		this.encodeImage(fc, this._srcPagePrevious, (previousEvent ? jsEvent_previous.toString() : null));
//		rw.endElement("td");
//	}
//	
//	private void encodeImage(FacesContext fc, String src, String jsEvent) throws IOException{
//		ResponseWriter rw = fc.getResponseWriter();
//		rw.startElement("img", this);
//		rw.writeAttribute("border", "0", null);
//		rw.writeAttribute("src", src, null);
//		rw.writeAttribute("alt", "", null);
//		rw.writeAttribute("class", this.styleClassImageMouseOut, null);
//		if (jsEvent != null) {
//			rw.writeAttribute("onclick", jsEvent, null);
//			rw.writeAttribute("onmouseover", "this.className='" + this.styleClassImageMouseOn + "'", null);
//			rw.writeAttribute("onmouseout", "this.className='" + this.styleClassImageMouseOut + "'", null);
//		}
//		rw.endElement("img");
//	}
//	
//	// 参考：encodeArrowPrevious
//	private void encodeArrowNext(FacesContext fc, String URLPrefix, String formId) throws IOException {
//		// 因为pageCurrent是从0算起，所以减1
//		Boolean nextEvent = this.pPageCurrent < this.pPageTotal - 1;
//		Long record_next = (this.pPageCurrent + 1) * this._pageSize;
//		Long record_last = (this.pPageTotal - 1) * this._pageSize;
//		
//		StringBuilder jsEvent_next = new StringBuilder("Q.F.UIScroller.imageLink(")
//		.append(" '" + URLPrefix + "'")
//		.append(",'" + record_next + "'")
//		.append(",'" + formId + "'")
//		.append(")");
//		
//		StringBuilder jsEvent_last = new StringBuilder("Q.F.UIScroller.imageLink(")
//		.append(" '" + URLPrefix + "'")
//		.append(",'" + record_last + "'")
//		.append(",'" + formId + "'")
//		.append(")");
//		
//		ResponseWriter rw = fc.getResponseWriter();
//		rw.startElement("td", this);
//		this.encodeImage(fc, this._srcPageNext, (nextEvent ? jsEvent_next.toString() : null));
//		rw.endElement("td");
//		
//		rw.startElement("td", this);
//		this.encodeImage(fc, this._srcPageLast, (nextEvent ? jsEvent_last.toString() : null));
//		rw.endElement("td");
//	}
//	
//	// ---------- calculate
//	
//	// 计算总页数
//	private Long calculatePageTotal(PageModel<Object> pm, Integer pageSize) {
//		Long total = pm.getTotal();
//		// 这里必须double之后再ceil，否则页数会减少
//		long pageTotal = (long) Math.ceil((double)total / pageSize);
//		return pageTotal;
//	}
//	
//	/**
//	 * 计算页面数组
//	 * @param pageTotal
//	 * @param pageDisplay
//	 * @param recordStart
//	 * @param pageSize
//	 * @return
//	 */
//	private long[][] calculatePages(Long pageTotal, Long pageDisplay,
//			Long recordStart, Integer pageSize) {
//		long startPage = 0;
//		long totalToDisplay = 0;
//		// 起始记录
//		long recordStartDisplay = 0;
//		// 取中点,始终将当前页显示在中间
//		long center = (long) Math.ceil(pageDisplay / 2);
//		// 如果所有页面数小于指定要显示的数目,则从0记录开始显示
//		if (pageTotal <= pageDisplay) {
//			recordStartDisplay = 0;
//			totalToDisplay = pageTotal;
//		} else {
//			// 否则尽量将记录向前移动一半，以让当前页显示在中间位置
//			recordStartDisplay = recordStart - center * pageSize;
//			if (recordStartDisplay < 0) {
//				recordStartDisplay = 0;
//			}
//			// 计算出起始记录页
//			startPage = recordStartDisplay / pageSize;
//			long theEnd = startPage + pageDisplay;
//			// 如果后面的页数不足以显示pageDisplay数目的记录
//			if (theEnd > pageTotal) {
//				long offset = theEnd - pageTotal;
//				// 则再次前移
//				recordStartDisplay -= offset * pageSize; 
//				if (recordStartDisplay < 0) {
//					recordStartDisplay = 0;
//				}
//			}
//		}
//		// 重新计算起始页
//		startPage = recordStartDisplay / pageSize;
//		
//		// 计算出剩下的页数
//		long leavePage = pageTotal - startPage;
//		totalToDisplay = pageDisplay <= leavePage ? pageDisplay : leavePage;
//		long[][] _pages = new long[(int) totalToDisplay][2];
//		for (int i = 0; i < totalToDisplay; i++) {
//			long[] page = new long[2];
//			// 页码
//			page[0] = startPage + i;
//			// 页记录
//			page[1] = recordStartDisplay + i * pageSize;
//			_pages[i] = page;
//		}
//		return _pages;
//	}
//	
//	/**
//	 * 计算当前所在页
//	 * @param recordStart
//	 * @param pageSize
//	 * @return
//	 */
//	private long calculatePageCurrent(long recordStart, int pageSize) {
//		long _pageCurrent = recordStart / pageSize; // 因为刚好整除，所以不用考虑余数咧
//		return _pageCurrent;
//	}
//	
//	
//	// 计算起始记录
//	private void calculateRecordStart(UIData target) {
//		// 优先从parameter中获取,注意检查recordStart,这是从客户端来的，可能存在各种可能的值
//		// 如非正数，非数字，超过最多记录数等。
//		Long recordStart = QFaces.convertToLong(QFaces.getParam(CONS_RECORD_START));
//		if (recordStart != null) {
//			this.pRecordStart = recordStart;
//		} else {
//			// 注意,如果用户在backingBean中绑定了uiData,并且可能在后台
//			// 手动设置了first（起始记录行）,那么这里需要使用该值.
//			// Note:对于分页查询来说，在bean中指定first属性一般都应该指定为0.
//			// 即从首记录开始显示。如：pageSize=10, 在后台查询数据后，默认first应该仍是0;
//			// 如果手动指定了first(通过绑定的uiData),如指定了first=2, 那么界面上将只显示
//			// 8条记录，因为pageSize=10,first=2,不要惊讶后面的数据为什么没有显示，因为这是
//			// 分页查询，只查了一页数据（10条记录）.
//			// 只有在反复查询的情况下，可能first属性被缓存起来的情况下，才应该手动重置first=0.
//			// 否则有时候你真的会看不到数据（有数据而没有显示），就如data只够1页，而first已经
//			// 指定到了第2页或更多.
//			Integer first = target.getFirst();	// 如果没有手动设置,那么这里target.getFirst()应该始终返回0
//			if (first != 0) {	// 这可以避免每次删除记录后都跳回到第1页
//				this.pRecordStart = first.longValue();
//			}
//		}
//		// 如果没有value,则默认为0. 在某种情况下,如用户手动在url中填入一个负值的recordStart,
//		// 这时需要将其置为0.
//		if (this.pRecordStart == null || this.pRecordStart < 0) {
//			this.pRecordStart = 0L;
//		}
//	}
//	
//	private void calculateSortBy() {
//		String sortField = QFaces.getParam(this.CONS_RECORD_SORT_BY);
//		Boolean isAsc = QFaces.convertToBoolean(QFaces.getParam(this.CONS_RECORD_SORT_ASC));
//		if (sortField != null) {
//			this._sortField = sortField;
//			this._isAsc = isAsc;
//		}
//	}
//	
//	private UIForm getForm(UIComponent ui) {
//		if (ui == null) {
//			return null;
//		} else {
//			if (ui instanceof UIForm) {
//				return (UIForm) ui;
//			} else {
//				return getForm(ui.getParent());
//			}
//		}
//	}
//
//	@Override
//	public String getFamily() {
//		return getClass().getName();
//	}
//}
